package com.dkm.orproject.dkmoa.service.serviceimpl;

import com.dkm.orproject.dkmoa.dao.*;
import com.dkm.orproject.dkmoa.domain.*;
import com.dkm.orproject.dkmoa.service.OaTravelBusinessFlowService;
import com.dkm.orproject.utils.utils.IdToobtainUtils;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 *  @ClassName : OaTravelBusinessFlowServiceImpl //类名
 *  @Description : OaTravelBusinessFlowAction的差旅流程service层实现类 //描述
 *  @Author : zmh //作者
 *  @Date: 2021-1-20 09:28  //时间
 */

@Service
@Transactional(rollbackFor = Exception.class)
public class OaTravelBusinessFlowServiceImpl implements OaTravelBusinessFlowService {
    /**
     * 员工差旅流程dao
     */
    @Resource
    private OaTravelBusinessFlowMapper oaTravelBusinessFlowMapper;

    /**
     * id生成工具
     */
    @Autowired
    IdToobtainUtils idUtils;

    /**
     * 流程记录日志
     */
    @Resource
    OaFlowScheduleMapper flowScheduleMapper;

    /**
     * 人员Mapper
     */
    @Resource
    OaPersonnelMapper personnelMapper;

    /**
     * 通知Mapper
     */
    @Resource
    OaMessageMapper messageMapper;

    /**
     * 通知人员关联Mapper
     */
    @Resource
    OaInformMapper informMapper;

    /**
     * 部门Mapper
     */
    @Resource
    OaDepartmentMapper departmentMapper;

    /**
         * 流程记录
     */
    OaFlowSchedule flowSchedule;

    /**
     * 开始节点id
     */
    static final Long START_NODE = 801769015692374016L;

    /**
     * 部门审核节点id
     */
    static final Long AUDIT_SECTION_NODE = 801769160697851904L;

    /**
     * 人事审核节点id
     */
    static final Long AUDIT_STAFFING_NODE = 801769575178973184L;

    /**
     * 总经理审核节点id
     */
    static final Long EX_STAFFING_NODE = 801770013672484864L;
    /**
     * 结束节点id
     */
    static final Long OVER_NODE = 801770190579838976L;

    /**
     * 人事审核通知
     */
    static final String STAFFING_CHECK_INFORM = "BUSINESStRISTAFF_INFO";


    /**
     * 总经理审核
     */
    static final String TRAVEL_EX_CHECK_INFORM = "BUSINESSGM_INFO";

    /**
     * 插入差旅流程
     * @param oaTravelBusinessFlow 差旅流程对象
     * @return 回调函数
     */
    @Override
    public int insertTravelBusinessFlow(OaTravelBusinessFlow oaTravelBusinessFlow) {
        oaTravelBusinessFlow.setPkTravelBusinessId(idUtils.getNumberId());
        return oaTravelBusinessFlowMapper.insertSelective(oaTravelBusinessFlow);
    }

    /**
     * 根据 Id 删除差旅流程对象
     *
     * @param pkTravelBusinessId 差旅流程的id值
     * @return 删除的条数
     */
    @Override
    public int deleteTravelBusinessFlowByPrimaryKey(Long pkTravelBusinessId) {
        return oaTravelBusinessFlowMapper.deleteByPrimaryKey(pkTravelBusinessId);
    }

    /**
     * 修改差旅详情
     *
     * @param oaTravelBusinessFlow 差旅详情对象
     * @return 回调函数
     */
    @Override
    public int updateTravelBusinessFlowByPrimaryKey(OaTravelBusinessFlow oaTravelBusinessFlow) {
        return oaTravelBusinessFlowMapper.updateByPrimaryKeySelective(oaTravelBusinessFlow);
    }

    /**
     * 根据id查询差旅详情
     *
     * @param pkTravelBusinessId 差旅详情的id值
     * @return 差旅详情对象
     */
    @Override
    public OaTravelBusinessFlow selectTravelBusinessFlowByPrimaryKey(Long pkTravelBusinessId) {
        return oaTravelBusinessFlowMapper.selectByPrimaryKey(pkTravelBusinessId);
    }

    /**
     * 起草人节点
     *
     * @param oaTravelBusinessFlow 差旅流程模型对象
     * @param oaPersonnel          操作人
     * @return
     */
    @Override
    public int add(OaTravelBusinessFlow oaTravelBusinessFlow, OaPersonnel oaPersonnel) {
        // 人员id
      oaTravelBusinessFlow.setPersonnelId(oaPersonnel.getPkPersonnelId());
        // D为部门审核
      oaTravelBusinessFlow.setIsRevision("D");
        // 进度设置为部门领导审核
      oaTravelBusinessFlow.setTravelBusinessSchedule(AUDIT_SECTION_NODE);

      if (ObjectUtils.isEmpty(oaTravelBusinessFlow.getPkTravelBusinessId())) {
          //差旅流程设置id
          oaTravelBusinessFlow.setPkTravelBusinessId(idUtils.getNumberId());
          //差旅流程名称
          oaTravelBusinessFlow.setTravelBusinessName(oaPersonnel.getPersonnelName() + "的差旅流程");
          //操作人名称
          oaTravelBusinessFlow.setCreatedBy(oaPersonnel.getPersonnelName());
          //增加差旅流程
          oaTravelBusinessFlowMapper.insertSelective(oaTravelBusinessFlow);
      } else {
          //修改差旅流程
          oaTravelBusinessFlowMapper.updateByPrimaryKeySelective(oaTravelBusinessFlow);
      }
        //新建流程记录和通知信息
        OaMessage message = addFlowSchedule(START_NODE, oaTravelBusinessFlow.getPkTravelBusinessId(), oaTravelBusinessFlow.getTravelBusinessName(), oaPersonnel, "2");

        //查询部门领导
        Long personnelId = departmentMapper.selectByPrimaryKey(oaPersonnel.getPkDepartmentId()).getPersonnelId();
        //新增关联
        return addInform(personnelId, message.getPkMessageId());
    }

    /**
     * 部门领导审核通过
     *
     * @param oaPersonnel
     * @param pkOaTravelBusinessId
     * @return
     */
    @Override
    public int sectionPass(OaPersonnel oaPersonnel, Long pkOaTravelBusinessId) {
        OaTravelBusinessFlow oaTravelBusinessFlow = oaTravelBusinessFlowMapper.selectByPrimaryKey(pkOaTravelBusinessId);
        // R为人事审核
        oaTravelBusinessFlow.setIsRevision("R");
        // 进度设置为人事审核
        oaTravelBusinessFlow.setTravelBusinessSchedule(AUDIT_STAFFING_NODE);

        System.out.println(oaTravelBusinessFlow.toString());
        //修改部门领导审核意见
        int row = oaTravelBusinessFlowMapper.updateByPrimaryKeySelective(oaTravelBusinessFlow);

        //新增通知信息
        OaMessage message = addFlowSchedule(AUDIT_SECTION_NODE, pkOaTravelBusinessId, oaTravelBusinessFlow.getTravelBusinessName(), oaPersonnel, "2");
        // 根据通知权限代码通知人事领导
        List<Long> personnelIds = personnelMapper.selectByHover(STAFFING_CHECK_INFORM);
        addInform(personnelIds, message.getPkMessageId());
        return row;
    }
    /**
     * 部门领导不同意
     * @param pkTravelBusinessId 流程id
     * @param oaPersonnel 操作人
     * @param formReason 不通过原因
     * @return
     */
    @Override
    public int sectionNoPass(Long pkTravelBusinessId, OaPersonnel oaPersonnel, String formReason) {
        OaTravelBusinessFlow oaTravelBusinessFlow = oaTravelBusinessFlowMapper.selectByPrimaryKey(pkTravelBusinessId);
        // c为申请人
        oaTravelBusinessFlow.setIsRevision("C");
        // 进度设置为起草
        oaTravelBusinessFlow.setTravelBusinessSchedule(START_NODE);
        //修改为起草阶段
        int row = oaTravelBusinessFlowMapper.updateByPrimaryKeySelective(oaTravelBusinessFlow);

        OaMessage message = addFlowSchedule(START_NODE, pkTravelBusinessId, oaTravelBusinessFlow.getTravelBusinessName(), oaPersonnel, formReason, "2");
        //通知起草人
        addInform(oaTravelBusinessFlow.getApplyPersonnelId(), message.getPkMessageId());
        return row;
    }

    /**
     * 人事审核(通过)
     *
     * @param pkTravelBusinessId 差旅流程id
     * @param oaPersonnel        操作人
     * @return 回调函数
     */
    @Override
    public int staffingPass(Long pkTravelBusinessId, OaPersonnel oaPersonnel) {
        //id查询
        OaTravelBusinessFlow oaTravelBusinessFlow = oaTravelBusinessFlowMapper.selectByPrimaryKey(pkTravelBusinessId);
        // 流程进度 设置流程进度 E总经理审核
        oaTravelBusinessFlow.setIsRevision("E");

        oaTravelBusinessFlow.setTravelBusinessSchedule(EX_STAFFING_NODE);
        //修改人事领导审核意见
        int row = oaTravelBusinessFlowMapper.updateByPrimaryKeySelective(oaTravelBusinessFlow);
        //新增通知信息
        OaMessage message = addFlowSchedule(AUDIT_STAFFING_NODE, pkTravelBusinessId, oaTravelBusinessFlow.getTravelBusinessName(), oaPersonnel, "2");
        // 根据通知权限代码通知总经理
        List<Long> personnelIds = personnelMapper.selectByHover(TRAVEL_EX_CHECK_INFORM);
        //关联通知信息
        addInform(personnelIds,message.getPkMessageId());
        return row;
    }

    /**
     * 人事不同意
     *
     * @param pkTravelBusinessId 差旅流程id
     * @param oaPersonnel        操作人
     * @return
     */
    @Override
    public int staffingNoPass(Long pkTravelBusinessId,OaPersonnel oaPersonnel,String formReason) {
        //id查询
        OaTravelBusinessFlow oaTravelBusinessFlow = oaTravelBusinessFlowMapper.selectByPrimaryKey(pkTravelBusinessId);
        //流程进度 设置流程进度 C起草人
        oaTravelBusinessFlow.setIsRevision("C");

        oaTravelBusinessFlow.setTravelBusinessSchedule(START_NODE);
        ///修改为起草阶段
        int row = oaTravelBusinessFlowMapper.updateByPrimaryKeySelective(oaTravelBusinessFlow);
        //新增通知信息
        OaMessage message = addFlowSchedule(AUDIT_STAFFING_NODE, pkTravelBusinessId, oaTravelBusinessFlow.getTravelBusinessName(), oaPersonnel, formReason, "2");

        //通知起草人
        addInform(oaTravelBusinessFlow.getApplyPersonnelId(), message.getPkMessageId());
        return row;
    }

    @Override
    public int exPass(Long pkOaTravelBusinessId, OaPersonnel oaPersonnel) {
        //id查询
        OaTravelBusinessFlow oaTravelBusinessFlow = oaTravelBusinessFlowMapper.selectByPrimaryKey(pkOaTravelBusinessId);
        //流程进度 设置流程进度 1 为结束
        oaTravelBusinessFlow.setIsRevision("1");

        oaTravelBusinessFlow.setTravelBusinessSchedule(OVER_NODE);
        ///修改为起草阶段
        int row = oaTravelBusinessFlowMapper.updateByPrimaryKeySelective(oaTravelBusinessFlow);
        //新增通知信息
        OaMessage message = addFlowSchedule(EX_STAFFING_NODE, pkOaTravelBusinessId, oaTravelBusinessFlow.getTravelBusinessName(), oaPersonnel, "2");
        OaMessage message1 = addFlowSchedule(EX_STAFFING_NODE, pkOaTravelBusinessId, oaTravelBusinessFlow.getTravelBusinessName(), oaPersonnel, "4");
        //通知起草人
        addInform(oaTravelBusinessFlow.getApplyPersonnelId(), message.getPkMessageId());
        return row;
    }

    @Override
    public int exNoPass(Long pkOaTravelBusinessId, String formReason, OaPersonnel oaPersonnel) {
        //id查询
        OaTravelBusinessFlow oaTravelBusinessFlow = oaTravelBusinessFlowMapper.selectByPrimaryKey(pkOaTravelBusinessId);
        //流程进度 设置流程进度 C起草人
        oaTravelBusinessFlow.setIsRevision("C");

        oaTravelBusinessFlow.setTravelBusinessSchedule(START_NODE);
        ///修改为起草阶段
        int row = oaTravelBusinessFlowMapper.updateByPrimaryKeySelective(oaTravelBusinessFlow);
        //新增通知信息
        OaMessage message = addFlowSchedule(EX_STAFFING_NODE, pkOaTravelBusinessId, oaTravelBusinessFlow.getTravelBusinessName(), oaPersonnel, formReason, "2");

        //通知起草人
        addInform(oaTravelBusinessFlow.getApplyPersonnelId(), message.getPkMessageId());
        return row;
    }

    /**
     * 关联通知
     * @param personnelId 通知人id
     * @param messageId 通知信息
     * @return 回调函数
     */
    private int addInform(Long personnelId,Long messageId){
        // 新建通知关联
        OaInform inform = new OaInform();
        // 通知关联id
        inform.setFkInformId(idUtils.getNumberId());
        // 设置为未读
        inform.setIsState("0");
        // 通知id
        inform.setMessageId(messageId);
        // 人员id
        inform.setPersonnelId(personnelId);
        // 新增通知关联集合
        return informMapper.insertSelective(inform);
    }

    /**
     * 批量关联通知
     * @param personnelIds 通知人id集合
     * @param messageId 通知信息
     * @return 回调函数
     */
    private int addInform(List<Long> personnelIds,Long messageId){
        int row=0;
        if(personnelIds== null || personnelIds.size()<1){
            return row;
        }
        // 通知人员关联集合
        List<OaInform> informs = new ArrayList<>();
        for (Long personnelId : personnelIds) {
            // 新建通知关联
            OaInform inform = new OaInform();
            // 通知关联id
            inform.setFkInformId(idUtils.getNumberId());
            // 设置为未读
            inform.setIsState("0");
            // 通知id
            inform.setMessageId(messageId);
            // 人员id
            inform.setPersonnelId(personnelId);
            informs.add(inform);
        }
        row = informMapper.insertAll(informs);
        // 新增通知关联集合
        return row;
    }

    /**
     * 不通过的情况下
     */
    private OaMessage addFlowSchedule(Long flowId, Long formId, String flowName, OaPersonnel personnel, String formReason, String number) {
        // 流程记录
        flowSchedule = new OaFlowSchedule();
        // 流程记录id
        flowSchedule.setPkFlowScheduleId(idUtils.getNumberId());
        // 离职流程id  起草节点
        flowSchedule.setFlowId(flowId);
        // 绑定表单
        flowSchedule.setFormId(formId);
        // 人员id
        flowSchedule.setPersonnelId(personnel.getPkPersonnelId());
        // 不通过原因
        flowSchedule.setFormReason(formReason);
        //审核人
        flowSchedule.setCreatedBy(personnel.getPersonnelName());
        // 新增转正流程记录
        flowScheduleMapper.insertSelective(flowSchedule);

        //删除旧通知
        int row=messageMapper.deleteByFormId(flowId);
        // 新建通知
        OaMessage message = new OaMessage();
        //通知id
        message.setPkMessageId(idUtils.getNumberId());
        //创建人
        message.setCreatedBy(personnel.getPersonnelName());
        //流程id
        message.setFormId(formId);
        // 通知标题
        message.setMessageName(flowName);
        //状态 2 待办
        message.setIsRevision(number);
        // 链接地址
        message.setMessageUrl("pages/dkmoa/front/flow/businessTrip/businessTripAdd.html?pkTravelBusinessId=");

        // 新增通知
        messageMapper.insertSelective(message);

        return message;
    }

    /**
     * 新增流程记录 和通知信息（通过的）
     * @param flowId 流程id
     * @param formId 表单id
     * @param flowName 流程名称
     * @param personnel 操作人
     * @return 通知信息
     */
    private OaMessage addFlowSchedule(Long flowId,Long formId,String flowName,OaPersonnel personnel,String number){
        // 流程记录
        flowSchedule = new OaFlowSchedule();
        // 流程记录id
        flowSchedule.setPkFlowScheduleId(idUtils.getNumberId());
        // 差旅流程id  起草节点
        flowSchedule.setFlowId(flowId);
        // 绑定表单
        flowSchedule.setFormId(formId);
        // 人员id
        flowSchedule.setPersonnelId(personnel.getPkPersonnelId());
        // 通过原因
        flowSchedule.setFormReason("  ");
        //审核人
        flowSchedule.setCreatedBy(personnel.getPersonnelName());
        // 新增差旅流程记录
        flowScheduleMapper.insertSelective(flowSchedule);

        //删除旧通知
        int row=messageMapper.deleteByFormId(formId);
        // 新建通知
        OaMessage message = new OaMessage();
        //通知id
        message.setPkMessageId(idUtils.getNumberId());
        //创建人
        message.setCreatedBy(personnel.getPersonnelName());
        //流程id
        message.setFormId(formId);
        // 通知标题
        message.setMessageName(flowName);
        //状态 2 待办
        message.setIsRevision(number);
        // 链接地址
        message.setMessageUrl("pages/dkmoa/front/flow/businessTrip/businessTripAudit.html?pkTravelBusinessId=");
        // 新增通知
        messageMapper.insertSelective(message);

        return message;
    }




    /**
     * 批量删除差旅流程
     *
     * @param ids
     * @return
     */
    @Override
    public int deleteAll(List<Long> ids) {
        return oaTravelBusinessFlowMapper.deleteAll(ids);
    }

    /**
     * 分页查询差旅流程
     *
     * @param oaTravelBusinessFlow
     * @param page
     * @param limit
     * @param startDate
     * @param endDate
     * @return
     */
    @Override
    public List<OaTravelBusinessFlow> findAll(OaTravelBusinessFlow oaTravelBusinessFlow, Integer page, Integer limit, String startDate, String endDate) {
        PageHelper.startPage(page, limit);
        return oaTravelBusinessFlowMapper.findAll(oaTravelBusinessFlow, startDate, endDate);
    }

    /**
     * 总行数
     *
     * @param oaTravelBusinessFlow
     * @param startDate
     * @param endDate
     * @return
     */
    @Override
    public Long rowCount(OaTravelBusinessFlow oaTravelBusinessFlow, String startDate, String endDate) {
        return oaTravelBusinessFlowMapper.rowCount(oaTravelBusinessFlow, startDate, endDate);
    }



    @Override
    public List<OaTravelBusinessFlow> selectAll(List<Long> list) {
        return oaTravelBusinessFlowMapper.selectAll(list);
    }
}
